﻿using Little.Soldier;
using Little.Soldier.Licensing;
using Little.Soldier.SWIFT.Definition;
using Little.Soldier.SWIFT.Validation;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.Xml;

namespace Little.Soldier.SWIFT
{
  [ToolboxItem(false)]
  [LicenseProvider(typeof(EncryptionProvider))]
  [DesignTimeVisible(false)]
  [Serializable]
  public class SwiftMessage : SwiftElement
  {
    private UnparsedTextList _UnparsedTexts = new UnparsedTextList();
    private List<SwiftBlockUser> _UserBlocks = new List<SwiftBlockUser>();
    private SwiftBlock1 _Block1;
    private SwiftBlock2 _Block2;
    private SwiftBlock3 _Block3;
    private SwiftBlock4 _Block4;
    private SwiftBlock5 _Block5;
    private readonly bool _InitBlocks;
    private string _Content;
    private long _Id;

    internal override SwiftDefinitionElement Definition
    {
      get
      {
        return (SwiftDefinitionElement) this.MsgDefinition();
      }
    }

    public virtual int FragmentCount
    {
      get
      {
        if (!this.IsFragment || this.Block4 == null)
          return 0;
        string tagValue = this.Block4.GetTagValue("203");
        try
        {
          return int.Parse(tagValue);
        }
        catch
        {
          throw new Exception("Value of the Tag '203' is not a number.");
        }
      }
    }

    public virtual int FragmentNumber
    {
      get
      {
        if (!this.IsFragment || this.Block4 == null)
          return 0;
        string tagValue = this.Block4.GetTagValue("202");
        try
        {
          return int.Parse(tagValue);
        }
        catch
        {
          throw new Exception("Value of the Tag '202' is not a number.");
        }
      }
    }

    public virtual long Id
    {
      get
      {
        return this._Id;
      }
      set
      {
        this._Id = value;
      }
    }

    internal string Content
    {
      get
      {
        return this._Content;
      }
      set
      {
        this._Content = value;
      }
    }

    public virtual string MessageType
    {
      get
      {
        SwiftBlock2 block2 = this.Block2;
        if (block2 != null && (block2 is SwiftBlock2Input || block2 is SwiftBlock2Output))
          return block2.MessageType;
        else
          return string.Empty;
      }
    }

    internal virtual UnparsedTextList UnparsedTexts
    {
      get
      {
        return this._UnparsedTexts;
      }
      set
      {
        this._UnparsedTexts = value;
      }
    }

    internal virtual int UnparsedTextsSize
    {
      get
      {
        if (this._UnparsedTexts == null)
          return 0;
        else
          return this._UnparsedTexts.Size;
      }
    }

    public virtual List<SwiftBlockUser> UserBlocks
    {
      get
      {
        return this._UserBlocks;
      }
      set
      {
        this._UserBlocks = value;
      }
    }

    public virtual bool IsFragment
    {
      get
      {
        SwiftBlock4 block4 = this.Block4;
        return block4 != null && (block4.GetTagValue("202") != null && block4.GetTagValue("203") != null);
      }
    }

    public virtual bool IsLastFragment
    {
      get
      {
        if (this.IsFragment)
        {
          try
          {
            return this.FragmentCount == this.FragmentNumber;
          }
          catch
          {
          }
        }
        return false;
      }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [Browsable(true)]
    public SwiftBlock1 Block1
    {
      get
      {
        return this._Block1;
      }
      set
      {
        this._Block1 = value;
      }
    }

    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SwiftBlock2 Block2
    {
      get
      {
        return this._Block2;
      }
      set
      {
        this._Block2 = value;
      }
    }

    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SwiftBlock3 Block3
    {
      get
      {
        return this._Block3;
      }
      set
      {
        this._Block3 = value;
      }
    }

    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SwiftBlock4 Block4
    {
      get
      {
        return this._Block4;
      }
      set
      {
        this._Block4 = value;
      }
    }

    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SwiftBlock5 Block5
    {
      get
      {
        return this._Block5;
      }
      set
      {
        this._Block5 = value;
      }
    }

    private SwiftMessage(SwiftElement parent) : base(parent, 0)
    {
        LicensingManager.Validate(typeof (SwiftMessage), (object) this);
        if (LicensingManager.EvalEnd)
            throw new LicenseException(typeof(SwiftMessage));
        
        this.InitSwiftMessageDefinition();
        this.InitSwiftSwiftElement(this.Definition, (SwiftElement)this);
    }

    public SwiftMessage(SwiftMessage message) : base((SwiftElement) null, 0)
    {
        LicensingManager.Validate(typeof(SwiftMessage), (object)this);
        if (LicensingManager.EvalEnd)
            throw new LicenseException(typeof(SwiftMessage));
      this.Block1 = message.Block1;
      if (this.Block1 != null)
        this.Block1.SwiftMessage = this;
      this.Block2 = message.Block2;
      if (this.Block2 != null)
        this.Block2.SwiftMessage = this;
      this.Block3 = message.Block3;
      if (this.Block3 != null)
        this.Block3.SwiftMessage = this;
      this.Block4 = message.Block4;
      if (this.Block4 != null)
        this.Block4.SwiftMessage = this;
      this.Block5 = message.Block5;
      if (this.Block5 != null)
        this.Block5.SwiftMessage = this;
      this.UserBlocks = message.UserBlocks;
      if (message.UserBlocks != null)
      {
        foreach (SwiftBlockBase swiftBlockBase in message.UserBlocks)
          swiftBlockBase.SwiftMessage = this;
      }
      this.InitSwiftMessageDefinition();
    }

    public SwiftMessage() : base((SwiftElement) null, 0)
    {
        LicensingManager.Validate(typeof(SwiftMessage), (object)this);
        if (LicensingManager.EvalEnd)
            throw new LicenseException(typeof(SwiftMessage));
      this._InitBlocks = false;
      this.InitBlocks();
      this.InitSwiftMessageDefinition();
      this.InitSwiftSwiftElement(this.Definition, (SwiftElement)this);
    }

    public SwiftMessage(bool initBlocks) : base((SwiftElement) null, 0)
    {
        LicensingManager.Validate(typeof(SwiftMessage), (object)this);
        if (LicensingManager.EvalEnd)
            throw new LicenseException(typeof(SwiftMessage));
      this._InitBlocks = initBlocks;
      if (initBlocks)
          this.InitBlocks();
      this.InitSwiftMessageDefinition();
      this.InitSwiftSwiftElement(this.Definition, (SwiftElement)this);
    }

    protected virtual void InitSwiftMessageDefinition()
    {
    }

    public virtual bool IsMTType(string type)
    {
      if (type.Length != 3)
        throw new Exception(((object) new StringBuilder().Append("The string must be exactly 3 chars Size (type=").Append(type).Append(")")).ToString());
      if (this.MessageType != null)
        return this.MessageType == type;
      else
        return false;
    }

        internal bool IsBlock4Error(List<ValidationError> parseError)
        {
            if (this.Definition.Elements.Count == 0)
                return true;
            if (this.GetListBlock4Tags(new List<SwiftDefinitionElement>()
            {
            this.Definition
            }, (SwiftElement) this, parseError).Count == this.Block4.Tags.Count)
                return true;
            parseError.Add(new ValidationError(ValidationErrorType.UsupportedBlockFormat, string.Format("Message {0} has wrong format in Block 4.", (object) this.Block2.MessageType)));
            return false;
        }

    public virtual bool Validate()
    {
      return this.Validate((List<ValidationError>) null);
    }

    public virtual bool Validate(List<ValidationError> errorList)
    {
      bool oldResult1 = true;
      bool oldResult2;
      if (this.Block1 != null)
      {
        oldResult2 = this.IsOldResult(oldResult1, this.Block1.Validate(errorList));
      }
      else
      {
        oldResult2 = false;
        errorList.Add(new ValidationError(ValidationErrorType.MissingBlock1, "Block 1 is empty."));
      }
      bool oldResult3;
      if (this.Block2 != null)
      {
        oldResult3 = this.IsOldResult(oldResult2, this.Block2.Validate(errorList));
      }
      else
      {
        oldResult3 = false;
        errorList.Add(new ValidationError(ValidationErrorType.MissingBlock2, "Block 2 is empty."));
      }
      if (this.Block3 != null)
        oldResult3 = this.IsOldResult(oldResult3, this.Block3.Validate(errorList));
      bool oldResult4;
      if (this.Block4 != null)
      {
        oldResult4 = this.IsOldResult(oldResult3, this.Block4.Validate(errorList));
      }
      else
      {
        oldResult4 = false;
        errorList.Add(new ValidationError(ValidationErrorType.MissingBlock4, "Block 4 is empty."));
      }
      if (this.Block5 != null)
        oldResult4 = this.IsOldResult(oldResult4, this.Block5.Validate(errorList));
      foreach (SwiftBlockUser swiftBlockUser in this.UserBlocks)
        oldResult4 = this.IsOldResult(oldResult4, swiftBlockUser.Validate(errorList));
      return oldResult4;
    }

    private bool IsOldResult(bool oldResult, bool newResult)
    {
      if (oldResult)
        return newResult;
      else
        return oldResult;
    }

    internal List<string> GetListBlock4Tags(List<SwiftDefinitionElement> elementsDefinition, SwiftElement element, List<ValidationError> parseError)
    {
      List<string> list = new List<string>();
      foreach (SwiftDefinitionElement definitionElement in elementsDefinition)
      {
        if (definitionElement is SwiftTagDefinition)
        {
          PropertyInfo property = element.GetType().GetProperty(definitionElement.Name);
          SwiftElement swiftElement1 = (SwiftElement) null;
          SwiftElement[] swiftElementArray = (SwiftElement[]) null;
          if (((SwiftTagDefinition) definitionElement).Multiple)
            swiftElementArray = (SwiftElement[]) property.GetValue((object) element, (object[]) null);
          else
            swiftElement1 = (SwiftElement) property.GetValue((object) element, (object[]) null);
          if (swiftElement1 != null)
          {
            string str = (string) swiftElement1.GetType().GetProperty("Value").GetValue((object) swiftElement1, (object[]) null);
            if (str != null)
            {
              list.Add(str);
              if (str == string.Empty && definitionElement.Mandatory)
                parseError.Add(new ValidationError(ValidationErrorType.UnsupportedValue, string.Format("Mandatory value in tag '{0}' cannot be empty.", (object) ((SwiftTagDefinition) definitionElement).TagName)));
            }
          }
          else
          {
            if (swiftElementArray == null)
              throw new Exception();
            foreach (SwiftElement swiftElement2 in swiftElementArray)
            {
              string str = (string) swiftElement2.GetType().GetProperty("Value").GetValue((object) swiftElement2, (object[]) null);
              if (str != null)
              {
                list.Add(str);
                if (str == string.Empty && definitionElement.Mandatory)
                  parseError.Add(new ValidationError(ValidationErrorType.UnsupportedValue, string.Format("Mandatory value in tag '{0}' cannot be empty.", (object) ((SwiftTagDefinition) definitionElement).TagName)));
              }
            }
          }
        }
        else if (definitionElement is SwiftMessageDefinition)
          list.AddRange((IEnumerable<string>) this.GetListBlock4Tags(definitionElement.Elements, element, parseError));
        else if (definitionElement is SwiftTagSequenceDefinition)
        {
          PropertyInfo property = element.GetType().GetProperty(definitionElement.Name);
          SwiftTagSequence[] swiftTagSequenceArray = (SwiftTagSequence[]) null;
          SwiftTagSequence swiftTagSequence1 = (SwiftTagSequence) null;
          if (((SwiftTagSequenceDefinition) definitionElement).Multiple)
            swiftTagSequenceArray = (SwiftTagSequence[]) property.GetValue((object) element, (object[]) null);
          else
            swiftTagSequence1 = (SwiftTagSequence) property.GetValue((object) element, (object[]) null);
          if (swiftTagSequenceArray != null)
          {
            foreach (SwiftTagSequence swiftTagSequence2 in swiftTagSequenceArray)
              list.AddRange((IEnumerable<string>) this.GetListBlock4Tags(definitionElement.Elements, (SwiftElement) swiftTagSequence2, parseError));
          }
          else if (swiftTagSequence1 != null)
            list.AddRange((IEnumerable<string>) this.GetListBlock4Tags(definitionElement.Elements, (SwiftElement) swiftTagSequence1, parseError));
          else if (definitionElement.Mandatory)
            throw new Exception();
        }
        else if (definitionElement is SwiftTagChoiceDefinition)
          list.AddRange((IEnumerable<string>) this.GetListBlock4Tags(definitionElement.Elements, element, parseError));
      }
      return list;
    }

    public SwiftTag GetTagByName(string tagName)
    {
      return this.Block4.GetTagByName(tagName);
    }

    public SwiftTag GetTagByNumber(int tagNumber)
    {
      return this.Block4.GetTagByNumber(tagNumber);
    }

    internal virtual SwiftMessageDefinition MsgDefinition()
    {
      return new SwiftMessageDefinition();
    }

    protected virtual string GetSwiftMessageXMLDefinition()
    {
      return string.Empty;
    }

    public virtual void AddBlock(SwiftBlockBase swiftBlock)
    {
      if (swiftBlock == null)
        return;
      if (!(swiftBlock is SwiftBlockUser))
      {
        int blockNumber = swiftBlock.BlockNumber;
        if (blockNumber < 1 || blockNumber > 5)
          throw new Exception("SwiftBlock.BlockNumber int did not return an int between 1-5");
        switch (blockNumber)
        {
          case 1:
            this.Block1 = swiftBlock as SwiftBlock1;
            break;
          case 2:
            this.Block2 = swiftBlock as SwiftBlock2;
            break;
          case 3:
            this.Block3 = swiftBlock as SwiftBlock3;
            break;
          case 4:
            this.Block4 = swiftBlock as SwiftBlock4;
            break;
          case 5:
            this.Block5 = swiftBlock as SwiftBlock5;
            break;
        }
      }
      else
        this.AddUserBlock((SwiftBlockUser) swiftBlock);
    }

    public virtual void AddUserBlock(SwiftBlockUser userBlock)
    {
      if (!userBlock.IsValidName())
        throw new Exception(((object) new StringBuilder().Append("Invalid Name for User Defined Blocks (").Append(userBlock.Name).Append(")")).ToString());
      if (this.UserBlocks == null)
        this.UserBlocks = new List<SwiftBlockUser>();
      int userBlockPosition = this.GetUserBlockPosition(userBlock.Name);
      if (userBlockPosition != -1)
        this.UserBlocks.Insert(userBlockPosition, userBlock);
      else
        this.UserBlocks.Add(userBlock);
    }

    public virtual void ClearBlocks()
    {
      this.Block1 = (SwiftBlock1) null;
      this.Block2 = (SwiftBlock2) null;
      this.Block3 = (SwiftBlock3) null;
      this.Block4 = (SwiftBlock4) null;
      this.Block5 = (SwiftBlock5) null;
      this.UserBlocks = new List<SwiftBlockUser>();
    }

    public virtual SwiftBlockBase GetBlock(int blockNumber)
    {
      if (1 > blockNumber || blockNumber > 5)
        throw new Exception(((object) new StringBuilder().Append("block index must be 1-5 (was ").Append(blockNumber).Append(")")).ToString());
      switch (blockNumber)
      {
        case 1:
          return (SwiftBlockBase) this.Block1;
        case 2:
          return (SwiftBlockBase) this.Block2;
        case 3:
          return (SwiftBlockBase) this.Block3;
        case 4:
          return (SwiftBlockBase) this.Block4;
        case 5:
          return (SwiftBlockBase) this.Block5;
        default:
          return (SwiftBlockBase) null;
      }
    }

    public virtual int GetBlockCount()
    {
      return this.GetBlockCount(true);
    }

    public virtual int GetBlockCount(bool includeUserBlocks)
    {
      int num = 0;
      if (this.Block1 != null && !this.Block1.IsEmpty)
        ++num;
      if (this.Block2 != null && !this.Block2.IsEmpty)
        ++num;
      if (this.Block3 != null && !this.Block3.IsEmpty)
        ++num;
      if (this.Block4 != null && !this.Block4.IsEmpty)
        ++num;
      if (this.Block5 != null && !this.Block5.IsEmpty)
        ++num;
      if (includeUserBlocks && this._UserBlocks != null)
        num += this.UserBlocks.Count;
      return num;
    }

    public virtual SwiftBlockUser GetUserBlock(int blockNumber)
    {
      return this.GetUserBlock(blockNumber.ToString());
    }

    public virtual SwiftBlockUser GetUserBlock(string blockName)
    {
      int userBlockPosition = this.GetUserBlockPosition(blockName);
      if (userBlockPosition != -1)
        return this._UserBlocks[userBlockPosition];
      else
        return (SwiftBlockUser) null;
    }

    public virtual int GetUserBlockPosition(string blockName)
    {
      switch (blockName)
      {
        case null:
          return -1;
        default:
          if (blockName != "" && this._UserBlocks != null)
          {
            for (int index = 0; index < this._UserBlocks.Count; ++index)
            {
              SwiftBlockUser swiftBlockUser = this._UserBlocks[index];
              if (swiftBlockUser != null && swiftBlockUser.Name == blockName)
                return index;
            }
            goto case null;
          }
          else
            goto case null;
      }
    }

    private void InitBlocks()
    {
      if (!this._InitBlocks)
        return;
      this.AddBlock((SwiftBlockBase) new SwiftBlock1(this));
      this.AddBlock((SwiftBlockBase) new SwiftBlock2Input(this));
      this.AddBlock((SwiftBlockBase) new SwiftBlock3(this));
      this.AddBlock((SwiftBlockBase) new SwiftBlock4(this));
      this.AddBlock((SwiftBlockBase) new SwiftBlock5(this));
      this.UserBlocks = new List<SwiftBlockUser>();
    }

    public virtual void RemoveUserBlock(int blockNumber)
    {
      if (!SwiftBlockUser.IsValidName(blockNumber))
        throw new Exception(((object) new StringBuilder().Append("Invalid Name for User Defined Blocks (").Append(blockNumber.ToString()).Append(")")).ToString());
      this.RemoveUserBlock(blockNumber.ToString());
    }

    public virtual void RemoveUserBlock(string blockName)
    {
      if (!SwiftBlockUser.IsValidName(blockName))
        throw new Exception(((object) new StringBuilder().Append("Invalid Name for User Defined Blocks (").Append(blockName).Append(")")).ToString());
      int userBlockPosition = this.GetUserBlockPosition(blockName);
      if (userBlockPosition == -1)
        return;
      this.UserBlocks.RemoveAt(userBlockPosition);
    }

        internal virtual void AddTex(SwiftMessage message)
        {
            this.UnparsedTexts.AddTex(message);
        }

        internal virtual void AddTex(string text)
        {
            this.UnparsedTexts.AddTex(text);
        }

    internal virtual SwiftMessage U0086(int index)
    {
      return this.UnparsedTexts.U0083U0003(index);
    }

    internal virtual string U0087(int index)
    {
      return this.UnparsedTexts.U0082U0003(index);
    }

    internal virtual bool U0088(int index)
    {
      return this.UnparsedTexts.U0084U0003(index);
    }

    internal virtual void SetBlock(IWriter visitor)
    {
      visitor.U009EU0002(this);
      SwiftBlock1 block1 = this.Block1;
      if (block1 != null)
      {
        visitor.SetBlock1(block1);
        visitor.SetBlock1(block1, block1.GetValue());
        visitor.CloseBlock1(block1);
      }
      SwiftBlock2 block2 = this.Block2;
      if (block2 != null)
      {
          visitor.SetBlock2(block2);
          visitor.SetBlock2(block2, block2.GetValue());
          visitor.CloseBlock2(block2);
      }
      SwiftBlock3 block3 = this.Block3;
      if (block3 != null)
      {
          visitor.SetBlock3(block3);
        this.SetBlock(block3, visitor);
        visitor.CloseBlock3(block3);
      }
      SwiftBlock4 block4 = this.Block4;
      if (block4 != null)
      {
          visitor.SetBlock4(block4);
        this.SetBlock(block4, visitor);
        visitor.CloseBlock4(block4);
      }
      SwiftBlock5 block5 = this.Block5;
      if (block5 != null)
      {
          visitor.SetBlock5(block5);
        this.SetBlock(block5, visitor);
        visitor.CloseBlock5(block5);
      }
      if (this._UserBlocks != null)
      {
        for (int index = 0; index < this.UserBlocks.Count; ++index)
        {
          SwiftBlockUser swiftBlockUser = this.UserBlocks[index];
          if (swiftBlockUser != null)
          {
            visitor.U009DU0002(swiftBlockUser);
            this.SetBlock(swiftBlockUser, visitor);
            visitor.U0096U0002(swiftBlockUser);
          }
        }
      }
      visitor.U0097U0002(this);
    }

    [Obsolete(null, false)]
    internal virtual void SetBlock(SwiftBlockBase block, IWriter visitor)
    {
      if (block is SwiftBlock3)
        goto label_8;
label_2:
      if (block is SwiftBlock4)
        this.SetBlock((SwiftBlock4) block, visitor);
      if (block is SwiftBlock5)
        this.SetBlock((SwiftBlock5) block, visitor);
      if (!(block is SwiftBlockUser))
        return;
      this.SetBlock((SwiftBlockUser) block, visitor);
      return;
label_8:
      this.SetBlock((SwiftBlock3) block, visitor);
      goto label_2;
    }

    internal virtual void SetBlock(SwiftBlock3 block, IWriter visitor)
    {
      foreach (SwiftTag t in block.Tags)
        visitor.U009FU0002(block, t);
    }

    internal virtual void SetBlock(SwiftBlock4 block, IWriter visitor)
    {
      foreach (SwiftTag t in block.Tags)
        visitor.U009FU0002(block, t);
    }

    internal virtual void SetBlock(SwiftBlock5 block, IWriter visitor)
    {
      foreach (SwiftTag t in block.Tags)
        visitor.U009FU0002(block, t);
    }

    internal virtual void SetBlock(SwiftBlockUser block, IWriter visitor)
    {
      foreach (SwiftTag t in block.Tags)
        visitor.U009FU0002(block, t);
    }

    public string ToXml()
    {
      return this.ToXml(true);
    }

    public string ToXmlRaw()
    {
      return this.ToXml(false);
    }

    private string ToXml(bool useDefinition)
    {
      if (useDefinition && this.GetType() == typeof (SwiftMessage))
      {
          SwiftMessage swiftMessage = FinancialMessages.GetSwiftMessage(this);
        if (swiftMessage.GetType() == typeof (SwiftMessage))
          throw new InvalidOperationException("Message cannot be serialized: unknown message type");
        else
          return swiftMessage.ToXml(useDefinition);
      }
      else
      {
        XmlDocument doc = new XmlDocument();
        string str = this.MessageType.Substring(0, 1);
        StringBuilder stringBuilder1 = new StringBuilder();
        stringBuilder1.Append("http://littlesoldier.com/Category");
        stringBuilder1.Append(str);
        stringBuilder1.Append("/MT");
        stringBuilder1.Append(this.MessageType);
        StringBuilder stringBuilder2 = new StringBuilder();
        stringBuilder2.Append("SWIFT_CATEGORY");
        stringBuilder2.Append(str);
        stringBuilder2.Append("_MT");
        stringBuilder2.Append(this.MessageType);
        stringBuilder2.Append("_Interchange");
        XmlNode newChild = (XmlNode) doc.CreateElement(((object) stringBuilder2).ToString(), ((object) stringBuilder1).ToString());
        doc.AppendChild(newChild);
        if (this.Block1 != null)
          newChild.AppendChild(this.Block1.ToXml(doc));
        if (this.Block2 != null)
          newChild.AppendChild(this.Block2.ToXml(doc));
        if (this.Block3 != null)
          newChild.AppendChild(this.Block3.ToXml(doc));
        if (this.Block4 != null)
        {
          if (useDefinition)
          {
            StringBuilder stringBuilder3 = new StringBuilder();
            stringBuilder3.Append("SWIFT_CATEGORY");
            stringBuilder3.Append(str);
            stringBuilder3.Append("_MT");
            stringBuilder3.Append(this.MessageType);
            XmlNode xmlNode = (XmlNode) doc.CreateElement(((object) stringBuilder3).ToString());
            newChild.AppendChild(xmlNode);
            SwiftMessageDefinition messageDefinition = this.MsgDefinition();
            List<SwiftTag> usedTags = new List<SwiftTag>();
            foreach (SwiftDefinitionElement elementDefinition in messageDefinition.Elements)
              this.U0007U0002(doc, xmlNode, (SwiftElement) this, elementDefinition, usedTags);
            StringBuilder stringBuilder4 = new StringBuilder();
            foreach (SwiftTag swiftTag in this.Block4.Tags)
            {
              if (!usedTags.Contains(swiftTag))
              {
                stringBuilder4.Append("Tag ");
                stringBuilder4.Append(swiftTag.Name);
                stringBuilder4.Append(" cannot be serialized. ");
              }
            }
            if (stringBuilder4.Length > 0)
              throw new InvalidOperationException("Message cannot be serialized due to invalid structure, not following the MT" + this.MessageType + " definition: " + ((object) stringBuilder4).ToString());
          }
          else
            newChild.AppendChild(this.Block4.ToXml(doc));
        }
        if (this.Block5 != null)
          newChild.AppendChild(this.Block5.ToXml(doc));
        foreach (SwiftBlockUser swiftBlockUser in this.UserBlocks)
          newChild.AppendChild(swiftBlockUser.ToXml(doc));
        return doc.InnerXml;
      }
    }

    private void U0007U0002(XmlDocument doc, XmlNode xmlParent, SwiftElement parentInstance, SwiftDefinitionElement elementDefinition, List<SwiftTag> usedTags)
    {
      if (!(elementDefinition is SwiftTagChoiceDefinition))
      {
        if (elementDefinition is SwiftTagSequenceDefinition)
        {
          int index = -1;
          int count;
          do
          {
            ++index;
            SwiftTagSequence swiftTagSequence = new SwiftTagSequence(parentInstance, index, (SwiftTagSequenceDefinition) elementDefinition);
            count = parentInstance.ListTags((SwiftElement) swiftTagSequence).Count;
            if (count > 0)
            {
              XmlElement element = doc.CreateElement(elementDefinition.Name);
              xmlParent.AppendChild((XmlNode) element);
              foreach (SwiftDefinitionElement elementDefinition1 in elementDefinition.Elements)
                this.U0007U0002(doc, (XmlNode) element, (SwiftElement) swiftTagSequence, elementDefinition1, usedTags);
            }
          }
          while (count > 0);
        }
        else
        {
          if (!(elementDefinition is SwiftTagDefinition))
            return;
          int index = -1;
          List<SwiftTag> list;
          do
          {
            ++index;
            SwiftTagWrapper swiftTagWrapper = new SwiftTagWrapper(parentInstance, index, elementDefinition);
            list = parentInstance.ListTags((SwiftElement) swiftTagWrapper);
            if (list.Count > 0)
            {
              XmlElement element = doc.CreateElement(elementDefinition.Name);
              xmlParent.AppendChild((XmlNode) element);
              element.InnerText = list[0].Value;
              usedTags.Add(list[0]);
            }
          }
          while (list.Count > 0);
        }
      }
      else
      {
        foreach (SwiftDefinitionElement elementDefinition1 in elementDefinition.Elements)
          this.U0007U0002(doc, xmlParent, parentInstance, elementDefinition1, usedTags);
      }
    }
  }
}
